package com.jeesite.common.shiro.filter;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.jeesite.common.codec.DesUtils;
import com.jeesite.common.config.Global;
import com.jeesite.common.entity.Extend;
import com.jeesite.common.lang.StringUtils;
import com.jeesite.common.pojo.*;
import com.jeesite.common.shiro.realm.WxUserRealm;
import com.jeesite.common.utils.HttpClientUtils;
import com.jeesite.common.utils.SpringUtils;
import com.jeesite.modules.sys.entity.User;
import com.jeesite.modules.sys.service.UserService;
import com.jeesite.modules.sys.utils.UserUtils;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter;
import org.springframework.util.Assert;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

/**
 * @ClassName WxLoginFilter
 * @Description 微信登录
 * @Author Spencer Zhang
 * @Date 2025/2/15 21:01
 */
@Slf4j
public class WxLoginFilter extends BasicHttpAuthenticationFilter {

    @Setter
    private WxUserRealm wxUserRealm; // 安全认证类

    private UserService userService;

    private String getRequestBody(ServletRequest request) throws IOException {
        StringBuilder stringBuilder = new StringBuilder();
        String line;
        BufferedReader reader = request.getReader();
        while ((line = reader.readLine()) != null) {
            stringBuilder.append(line);
        }
        return stringBuilder.toString();
    }

    public UserService getUserService() {
        if (userService == null) {
            userService = SpringUtils.getBean(UserService.class);
        }
        return userService;
    }

    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        try {
            Map<String, String[]> params = new HashMap<>();
            params.putAll(request.getParameterMap());
            String json = getRequestBody(request);
            JSONObject jsonObject = JSON.parseObject(json);
            String phone = jsonObject.get("phone").toString();
            String code = jsonObject.get("code").toString();
            //微信获取用户信息
            Map<String, Object> ps = new HashMap<>();
            ps.put("appid", "wx2ba65b4022b5220a");
            ps.put("secret", "c9ebfaa4c1ebb62d2b95319baa633b61");
            ps.put("js_code", code);
            ps.put("grant_type", "authorization_code");
            WxLoginEntity entity = HttpClientUtils.sendMsg("get",
                    "https://api.weixin.qq.com/sns/jscode2session",
                    ps,
                    WxLoginEntity.class);

            Assert.isNull(entity.getErrMsg(), entity.getErrMsg());
            String openId = entity.getOpenId();
            String sessionKey = entity.getSessionKey();
            Assert.notNull(openId, "未找到微信用户信息");
            Assert.notNull(phone, "缺少手机号");

//            String openId = "123";
//            String sessionKey = "123";

            getUserService();
            //处理用户
            User u = new User();
            u.setLoginCode(phone);
            User user = userService.getByLoginCode(u);
            if (user == null) {
                u.setIsNewRecord(true);
                u.setUserCode(phone);
                u.setUserName(phone);
                u.setLoginCode(phone);
                String password = "123456";
                String secretKey = Global.getProperty("shiro.loginSubmit.secretKey");
                if (StringUtils.isNotBlank(secretKey)) {
                    String encodePwd = DesUtils.encode(password, secretKey);
//                    u.setPassword(DesUtils.encode(sessionKey, secretKey));
                    u.setPassword(encodePwd);
                } else {
                    String encodePwd = userService.encryptPassword(password);
//                    u.setPassword(userService.encryptPassword(sessionKey));
                    u.setPassword(encodePwd);
                }
                u.setWxOpenid(openId);
                u.setMgrType(User.MGR_TYPE_NOT_ADMIN);
                u.setRefCode(phone);
                u.setRefName(phone);
                u.setUserType("employee");
                Extend extend = new Extend();
                extend.setExtendS2(sessionKey);
                u.setExtend(extend);
                userService.insert(u);
                //新增用户角色关系数据
//            SysUserRole sysUserRole = new SysUserRole();
//            sysUserRole.setUserCode(u.getUserCode());
//            sysUserRole.setRoleCode("user");//普通用户
//            sysUserRoleService.insertUserRole(sysUserRole);
            } else {
                u = user;
                u.setWxOpenid(openId);
                Extend extend = u.getExtend();
                if (extend != null) {
                    extend.setExtendS2(sessionKey);
                } else {
                    Extend e = new Extend();
                    e.setExtendS2(sessionKey);
                    u.setExtend(e);
                }
                userService.save(u);
            }

            String pwd = u.getExtend().getExtendS2();
            params.put("username", new String[]{phone});
            params.put("password", new String[]{pwd});
            request = new WxHttpServletRequest((HttpServletRequest) request, params);
            return executeLogin(request, response);
        } catch (Exception e) {
            log.error(e.getMessage());
            request.setAttribute("message", "登录失败");
        }

        String message = request.getAttribute("message").toString();
        StringBuilder sb = new StringBuilder("{\"result\": \"false\"");
        sb.append(",\"message\":\"" + (message == null ? "登录失败" : message) + "\"}");
        setResult(response, sb.toString());
        return false;
    }

    private void setResult(ServletResponse response, String s) {
        response.setContentType("application/json");
        response.setCharacterEncoding("UTF-8");
        try (PrintWriter out = response.getWriter()) {
            out.print(s);
            out.flush();
        } catch (IOException ioException) {
            log.error(ioException.getMessage());
        }
    }

    /**
     * 创建登录授权令牌
     */
    @Override
    protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) {
        Map<String, String[]> map = request.getParameterMap();
        String phone = map.get("username")[0];
        String pwd = map.get("password")[0];
        return new WxUsernameSessionToken(phone, pwd, "wxLogin");
    }

    /**
     * 登录成功调用事件
     */
    @Override
    protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request, ServletResponse response) throws Exception {
        User user = UserUtils.getUser();
        Session session = UserUtils.getSession();
        setResult(response, JSON.toJSONString(LoginRespones.builder()
                .user(new LoginUser(user))
                .result("true")
                .message("登录成功！")
                .sessionid((String) session.getId())
                .build()));
//        WebUtils.issueRedirect(request, response, "/api/wx/user/wxLogin", null, true);
        return false;
    }

}